function getsec(str) {
  let str1 = str.substring(1, str.length) * 1
  let str2 = str.substring(0, 1)
  if (str2 === 's') {
    return str1 * 1000
  } else if (str2 === 'h') {
    return str1 * 60 * 60 * 1000
  } else if (str2 === 'd') {
    return str1 * 24 * 60 * 60 * 1000
  }
}

/*
 * cookie相关模块
 * 设定过期时间的使用示例：
 * s20是代表20秒
 * h是指小时，如12小时则是：h12
 * d是天数，30天则：d30
 * setCookie("name","hayden","s20");
 */
export function setCookie(name, value, time) {
  if (!time) {
    document.cookie = name + '=' + value + ';path=/'
    return
  }
  let strsec = getsec(time)
  let exp = new Date()
  exp.setTime(exp.getTime() + strsec * 1)
  document.cookie = name + '=' + value + ';expires=' + exp.toGMTString() + ';path=/'
}

export function delCookie(name) {
  let exp = new Date()
  exp.setTime(exp.getTime() - 1)
  let cval = getCookie(name)
  if (cval != null) {
    document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString() + ';path=/'
  }
}

/**
 * @description 获取cookie数据
 * @export
 * @param {string} name
 * @returns
 */
export function getCookie(name) {
  const arr = document.cookie.split('; ')
  for (let i = 0; i < arr.length; i++) {
    const arrName = arr[i].split('=')
    if (arrName[0] === name) {
      return arrName[1]
    }
  }
  return ''
}

/**
 * @description 获取userData数据
 * @export
 * @param {string} name
 * @returns
 */
export function getUserData(name) {
  return localStorage.getItem(name)
}

/**
 * @description 对象自身是否包含某个属性
 * @export
 * @param {object} obj
 * @param {string} key
 * @returns
 */
export function objectHasOwnProperty(obj, key) {
  return Object.hasOwnProperty.call(obj, key)
}

/**
 * @description 数字添加千分位逗号
 * @export
 * @param {number|string} num
 * @returns
 */
export function number2Thousands(num) {
  num = (num || 0).toString()
  const pointIndex = num.indexOf('.')
  if (pointIndex === -1) {
    return num.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  }
  return num.substr(0, pointIndex).replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') + num.substr(pointIndex)
}

/**
 * @description 格式化日期
 * @export
 * @param {Date|string} time
 * @param {'date'|'time'|'datetime'|undefined} type
 * @returns
 */
export function formatDateTime(time, type) {
  const date = new Date(time)
  if (!date) return

  const y = date.getFullYear()
  let m = date.getMonth() + 1
  m = m < 10 ? (`0${m}`) : m
  let d = date.getDate()
  d = d < 10 ? (`0${d}`) : d
  let h = date.getHours()
  h = h < 10 ? (`0${h}`) : h
  let minute = date.getMinutes()
  minute = minute < 10 ? (`0${minute}`) : minute
  let sec = date.getSeconds()
  sec = sec < 10 ? (`0${sec}`) : sec

  const dateStr = `${y}-${m}-${d}`
  const timeStr = `${h}:${minute}:${sec}`

  switch (type) {
    case 'date':
      return dateStr
    case 'time':
      return timeStr
    case 'datetime':
    default:
      return `${dateStr} ${timeStr}`
  }
}

/**
 * @description 金额格式化 1000 -> 1k  10000 -> 1w
 * @export
 * @param {number|string} price
 * @returns
 */
export function formatPrice(price) {
  if (!price) {
    return 0
  }

  const arr = price.toString().split('.')
  const integer = arr[0]

  if (integer.length > 4) {
    return Number(Math.ceil((integer / 1000).toFixed(1)) / 10) + 'w'
  }

  if (integer.length > 3) {
    return Number(Math.ceil((integer / 100).toFixed(1)) / 10) + 'k'
  }

  return price
}

/**
 * @description 定时请求
 * @export
 * @param {object} option
 * option属性说明
 * @property {function} request 请求函数
 * @property {number} interval 定时请求的间隔时间
 * @property {boolean} immediate 是否立即执行一次
 * @property {boolean} errorContinue 是否忽略报错继续执行
 */
export function loopRequest({
  request,
  interval,
  immediate = false,
  errorContinue = false
}) {
  let timer = null
  // 由于request为异步任务，所以当清除定时器时，异步任务可能正在执行中，这时，循环并未结束
  // 所以添加标记位，保证循环中断
  let abort = false

  function loop() {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      if (abort) return
      request()
        .then(() => {
          if (abort) return
          loop()
        })
        .catch(error => {
          if (abort) return
          if (!errorContinue) {
            clearTimeout(timer)
            throw error
          } else {
            loop()
          }
        })
    }, interval)
  }
  if (immediate) {
    request()
      .then(() => {
        if (abort) return
        loop()
      })
      .catch(error => {
        if (abort) return
        if (!errorContinue) {
          clearTimeout(timer)
          throw error
        } else {
          loop()
        }
      })
  } else {
    loop()
  }

  return {
    stop() {
      clearTimeout(timer)
      abort = true
    }
  }
}

// 进入全屏
export function requestFullScreen() {
  const de = document.documentElement
  if (de.requestFullscreen) {
    de.requestFullscreen()
  } else if (de.mozRequestFullScreen) {
    de.mozRequestFullScreen()
  } else if (de.webkitRequestFullScreen) {
    de.webkitRequestFullScreen()
  } else if (de.msRequestFullscreen) {
    de.msRequestFullscreen()
  }
}

// 退出全屏
export function exitFullscreen() {
  const de = document
  if (de.exitFullscreen) {
    de.exitFullscreen()
  } else if (de.mozCancelFullScreen) {
    de.mozCancelFullScreen()
  } else if (de.webkitCancelFullScreen) {
    de.webkitCancelFullScreen()
  } else if (de.msExitFullscreen) {
    de.msExitFullscreen()
  }
}

/**
* @description 判断是否是对象，排除null，来自于underscore
* @param {any} obj
* @returns
*/
export function isObject(obj) {
  return obj === Object(obj)
}

/**
 * @description 获取对象多层属性值，key可以嵌套多层 ‘message.code’
 * @param {object} obj
 * @param {string} keys
 */
export function getObjMultiLevelValue(obj, keys) {
  if (!isObject(obj)) return null

  const keyArr = keys.split('.')
  let value = obj

  try {
    keyArr.forEach((key) => {
      if (!isObject(value)) {
        throw new Error('end')
      }
      if (key in value) {
        value = value[key]
      } else {
        throw new Error('end')
      }
    })
    // eslint-disable-next-line no-empty
  } catch (error) { }

  return value
}

/**
 * 获取浏览器类型
 */
export function getBrowserType() {
  let userAgent = navigator.userAgent // 取得浏览器的userAgent字符串
  let isOpera = userAgent.indexOf('Opera') > -1 // 判断是否Opera浏览器
  let isIE = userAgent.indexOf('compatible') > -1 &&
    userAgent.indexOf('MSIE') > -1 && !isOpera // 判断是否IE浏览器
  let isEdge = userAgent.indexOf('Edge') > -1 // 判断是否IE的Edge浏览器
  let isFF = userAgent.indexOf('Firefox') > -1 // 判断是否Firefox浏览器
  let isSafari = userAgent.indexOf('Safari') > -1 &&
    userAgent.indexOf('Chrome') === -1 // 判断是否Safari浏览器
  let isChrome = userAgent.indexOf('Chrome') > -1 &&
    userAgent.indexOf('Safari') > -1 // 判断Chrome浏览器

  let isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1
  if (isIE) {
    let reIE = new RegExp('MSIE (\\d+\\.\\d+);')
    reIE.test(userAgent)
    let fIEVersion = parseFloat(RegExp['$1'])
    if (fIEVersion === 7) {
      return 'IE7'
    } else if (fIEVersion === 8) {
      return 'IE8'
    } else if (fIEVersion === 9) {
      return 'IE9'
    } else if (fIEVersion === 10) {
      return 'IE10'
    } else {
      return '0'
    }
  }
  if (isIE11) {
    return 'IE11'
  }
  if (isOpera) {
    return 'Opera'
  }
  if (isEdge) {
    return 'Edge'
  }
  if (isFF) {
    return 'FF'
  }
  if (isSafari) {
    return 'Safari'
  }
  if (isChrome) {
    return 'Chrome'
  }
}

/**
* 将时间戳转换为日期格式
* @param {string} time
*/
export function transformTimestamp(time) {
  let date = new Date(time)
  let y = date.getFullYear()
  let m = date.getMonth() + 1
  m = m < 10 ? ('0' + m) : m
  let d = date.getDate()
  d = d < 10 ? ('0' + d) : d
  let h = date.getHours()
  h = h < 10 ? ('0' + h) : h
  let minute = date.getMinutes()
  minute = minute < 10 ? ('0' + minute) : minute
  let sec = date.getSeconds()
  sec = sec < 10 ? ('0' + sec) : sec
  return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + sec
}

/**
 * 往前推某个日期
 * @param {Number} time
 */
export function getDate(time) {
  let date = new Date() // 当前日期
  let newDate = new Date()
  newDate.setDate(date.getDate() + time) // 官方文档上虽然说setDate参数是1-31,其实是可以设置负数的
  let newTime = newDate.getFullYear() + '-' + (newDate.getMonth() + 1) + '-' + newDate.getDate()
  return newTime
}

/**
 * 渐变色获取
 * @param {*} start
 * @param {*} end
 * @param {*} steps
 * @param {*} gamma
 */
export function gradientColors(start, end, steps, gamma) {
  let i; let j; let ms; let me; let output = []; let so = []
  gamma = gamma || 1
  let normalize = function (channel) {
    return Math.pow(channel / 255, gamma)
  }
  // zero-pad 1 digit to 2
  let pad = function (s) {
    return (s.length === 1) ? '0' + s : s
  }
  // convert #hex notation to rgb array
  let parseColor = function (hexStr) {
    return hexStr.length === 4 ? hexStr.substr(1).split('').map(function (s) { return 0x11 * parseInt(s, 16) }) : [hexStr.substr(1, 2), hexStr.substr(3, 2), hexStr.substr(5, 2)].map(function (s) { return parseInt(s, 16) })
  }
  start = parseColor(start).map(normalize)
  end = parseColor(end).map(normalize)
  for (i = 0; i < steps; i++) {
    ms = i / (steps - 1)
    me = 1 - ms
    for (j = 0; j < 3; j++) {
      so[j] = pad(Math.round(Math.pow(start[j] * me + end[j] * ms, 1 / gamma) * 255).toString(16))
    }
    output.push('#' + so.join(''))
  }
  return output
}

// 对象数组深拷贝
export function deepCopy(p, c) {
  const nc = c || {}
  for (const i in p) {
    if (p[i] !== null && typeof p[i] === 'object') {
      nc[i] = p[i].constructor === Array ? [] : {}
      deepCopy(p[i], nc[i])
    } else {
      nc[i] = p[i]
    }
  }
  return nc
}